<template>
  <div>
    <formula-code-mirror
      ref="formulaCodeMirror"
      :fields="filterFields"
      :mode="mode"
      :value="cmValue"
    >
      <template #tips>
        <slot name="tips"></slot>
      </template>
    </formula-code-mirror>
    <el-divider />
    <el-row :gutter="20">
      <el-col :span="6">
        <div class="box-card">
          <div class="header">
            <el-input
              v-model="filedNameValue"
              :placeholder="$t('formgen.funcalc.varName')"
              prefix-icon="ele-Search"
              size="default"
              @input="handleFilterFields"
            />
          </div>
          <div class="body">
            <el-scrollbar
              ref="scrollMenuRef"
              class="scrollbar-box"
            >
              <ul class="field-list">
                <li
                  v-for="f in filterFields"
                  :key="f.key"
                  class="field"
                  @click="handleFieldClick(f)"
                >
                  <el-tooltip
                    :content="f.fullLabel"
                    class="box-item"
                    effect="tduck"
                    placement="top"
                  >
                    <span class="menu-item with-capsule">{{ f.label }}</span>
                  </el-tooltip>
                  <div class="opertion-btns">
                    <el-tooltip
                      v-if="isLabelTag(f.key)"
                      :content="$t('formgen.funcalc.label')"
                      effect="tduck"
                      placement="top"
                    >
                      <el-icon
                        @click="
                          (event: MouseEvent) => {
                            event.stopPropagation();
                            handleFieldClick({
                              key: f.key + 'label',
                              label: f.label + '(文字)',
                              fullLabel: f.fullLabel + '(文字)'
                            });
                          }
                        "
                      >
                        <TablerTextSize />
                      </el-icon>
                    </el-tooltip>
                    <el-tooltip
                      v-if="f.key.indexOf('radio') > -1 || f.key.indexOf('checkbox') > -1"
                      :content="$t('formgen.funcalc.scoreVal')"
                      effect="tduck"
                      placement="top"
                    >
                      <el-icon
                        @click="
                          (event: MouseEvent) => {
                            event.stopPropagation();
                            handleFieldClick({
                              key: f.key + 'score',
                              label: f.label + '(分值)',
                              fullLabel: f.fullLabel + '(分值)'
                            });
                          }
                        "
                      >
                        <TablerNumber />
                      </el-icon>
                    </el-tooltip>
                  </div>
                </li>
              </ul>
            </el-scrollbar>
          </div>
        </div>
      </el-col>
      <el-col :span="10">
        <div class="box-card">
          <div class="header">
            <el-input
              v-model="funNameValue"
              :placeholder="$t('formgen.funcalc.searchFun')"
              prefix-icon="ele-Search"
              size="default"
            />
          </div>
          <div class="body">
            <el-scrollbar
              ref="scrollMenuRef"
              class="scrollbar-box"
            >
              <el-tree
                ref="funTree"
                :data="formulaList"
                :filter-node-method="filterNode"
                :props="defaultProps"
                class="fun-tree"
                @node-click="handleNodeClick"
              >
                <template #default="{ node, data }">
                  <span
                    class="custom-tree-node"
                    @mouseenter="handleFunMouseenter(data)"
                  >
                    <span>{{ node.label }}</span>
                  </span>
                </template>
              </el-tree>
            </el-scrollbar>
          </div>
        </div>
      </el-col>
      <el-col :span="8">
        <div class="intro-box">
          <span v-html="selectFun.intro"></span>
        </div>
      </el-col>
    </el-row>
  </div>
</template>

<script lang="ts" setup>
import { onMounted, ref, watch } from "vue";
import FormulaCodeMirror from "./CodeMirror.vue";
import { formulaList } from "./FormulaList";
import { removeHtmlTag } from "../../utils";
import TablerTextSize from "~icons/tabler/text-size";
import TablerNumber from "~icons/tabler/number";
import { isLabelTag } from "@/views/formgen/components/GenerateForm/FormItemLabel";

interface Field {
  key: string;
  fullLabel: string;
  label: string;
}

interface FormulaFunction {
  name: string;
  intro: string;
  children?: FormulaFunction[];
}

interface Props {
  cmValue?: string;
  fields?: any[];
  mode?: string;
}

const props = withDefaults(defineProps<Props>(), {
  cmValue: "",
  fields: () => [],
  mode: "text/x-formula"
});

const emit = defineEmits<{
  (e: "save", value: string): void;
}>();

const tempFields = ref<Field[]>([]);
const filterFields = ref<Field[]>([]);
const filedNameValue = ref("");
const funNameValue = ref("");
const selectFun = ref<FormulaFunction>({
  name: "",
  intro: ""
});

const defaultProps = {
  children: "children",
  label: "name"
};

const formulaCodeMirror = ref<InstanceType<typeof FormulaCodeMirror> | null>(null);
const scrollMenuRef = ref();
const funTree = ref();

const getFieldsList = () => {
  const subStr = (str: string): string => {
    return str.replace(/[\r\s]/g, "").substring(0, 10);
  };

  tempFields.value = props.fields
    .map(item => {
      let label = removeHtmlTag(item.config.label);
      if (item.vModel.startsWith("sub_form")) {
        return item.childList.map((subItem: any) => {
          const subLabel = label + "-" + removeHtmlTag(subItem.config.label);
          return {
            key: item.vModel + "," + subItem.vModel,
            fullLabel: subLabel,
            label: subStr(subLabel)
          };
        });
      } else {
        return [{ key: item.vModel, fullLabel: label, label: subStr(label) }];
      }
    })
    .flat();
  filterFields.value = tempFields.value;
};

const filterNode = (value: string, data: FormulaFunction): boolean => {
  if (!value) return true;
  return data.name.indexOf(value) !== -1;
};

const handleFilterFields = () => {
  if (!filedNameValue.value) {
    filterFields.value = tempFields.value;
    return;
  }
  filterFields.value = tempFields.value.filter(item => {
    return item.label.indexOf(filedNameValue.value) > -1;
  });
};

const handleFieldClick = (field: Field) => {
  formulaCodeMirror.value?.insertVariable(field.key, field.label);
};

const handleFunMouseenter = (data: FormulaFunction) => {
  selectFun.value = data;
};

const handleNodeClick = (data: FormulaFunction, node: any) => {
  if (node.level === 1) {
    return;
  }
  selectFun.value = data;
  formulaCodeMirror.value?.insertFunction(data.name);
};

const getValue = () => {
  return formulaCodeMirror.value?.getValue() || "";
};

watch(
  () => props.fields,
  () => {
    getFieldsList();
  },
  { deep: true }
);

watch(funNameValue, val => {
  funTree.value?.filter(val);
});

onMounted(() => {
  getFieldsList();
});

defineExpose({
  getValue
});
</script>

<style lang="scss" scoped>
.box-card {
  .body {
    border: 1px solid #dfe4ed;
    border-top: none;
    height: 280px;
  }
}

.scrollbar-box {
  height: 100% !important;
  padding-bottom: 0px !important;
}

.intro-box {
  height: 100%;
  border: 1px solid #dfe4ed;
  padding: 10px;
}

.field-list {
  display: block;

  .field {
    list-style-type: none;
    line-height: 30px;
    padding-left: 10px;
    overflow: hidden;
    white-space: nowrap;
    position: relative;
  }

  .field:hover {
    background: #f6f8f9;
    color: rgba(0, 0, 0, 0.75);
    cursor: pointer;
  }

  .opertion-btns {
    height: 28px;
    line-height: 25px;
    position: absolute;
    right: 5px;
    display: inline-flex;
    align-items: center;
    font-size: 18px;
    color: var(--el-text-color-primary);
    justify-content: flex-end;
    gap: 3px;
  }
}
</style>
